package ac.svn.accesscontrol.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ac.notification.event.INotificationListener;
import ac.notification.event.NotificationEvent;
import ac.notification.manager.NotificationRegistrar;
import ac.svn.accesscontrol.io.FileReader;
import ac.svn.accesscontrol.manager.SVNInfoManager;
import ac.svn.accesscontrol.store.AccessUnit;
import ac.svn.accesscontrol.store.ISVNIdentifier;
import ac.svn.accesscontrol.store.SVNGroup;
import ac.svn.accesscontrol.store.SVNLocation;
import ac.svn.accesscontrol.store.SVNTag;
import ac.svn.accesscontrol.store.SVNUser;
import ac.svn.accesscontrol.utils.TagParser;

public class TagProcessor implements INotificationListener,ISVNIdentifier
{
	private FileReader fileReader;
	private Set<String> subscriptions;
	private SVNInfoManager infoManager;
	public TagProcessor()
	{
		fileReader = new FileReader();
		subscriptions = new HashSet<String>(5);
		infoManager = SVNInfoManager.getInfoManager();
		NotificationRegistrar.registerListener(this);
	}

	@Override
	public Set<String> declaredSubscriptionSet() {
		subscriptions.add(CMD_PROCESS_FILE);
		subscriptions.add(CMD_SAVE_FILE);
		return subscriptions;
	}

	@Override
	public void receiveEvent(NotificationEvent ne) {
		if(ne.getPropertyIdentifier().contains(CMD_PROCESS_FILE))
		{
			String filePath = (String) ne.getPropertyValue();;
			if(fileReader.readFile(filePath ))
			{
				processFile();
			}
			NotificationEvent n = new NotificationEvent(N_UPDATE_USERS);
			NotificationRegistrar.dispatchNotification(n);
		}
		else if(ne.getPropertyIdentifier().contains(CMD_PROCESS_FILE))
		{

		}
	}

	private void processFile() {
		Map<String,SVNTag> tagsMap = createTags();
		//Parse values held in tags.
		TagParser tagParser = new  TagParser();
		//Final parsed tags.
		Map<String, Set<String>> parsedTag = tagParser.getParsedTag();

		for(String tagId:tagsMap.keySet())
		{
			SVNTag tag = tagsMap.get(tagId);
			tagParser.parseTag(tag);
			System.out.println("----------------------------------------------------------------------------------------------------------");
			System.out.println("Tag: " + tagParser.getTagValue() + "\t Type: " + tagParser.getTagType());

			/*System.out.println("Entity: " + entity);
			Set<String> attributes = parsedTag.get(entity);
			System.out.println("Attributes: " + attributes);*/


			//Update information in SVN Information Manager.
			if(TagParser.TAG_GROUP == tagParser.getTagType())
			{
				for(String grpAlias: tagParser.getParsedTag().keySet())
				{
					SVNGroup group = infoManager.getGroup(grpAlias);
					//Create new group if group does not exist.
					if(null == group )
					{
						group = new SVNGroup(grpAlias,grpAlias);
						Set<String> userAliases = tagParser.getParsedTag().get(grpAlias);
						for(String userAlias : userAliases)
						{
							if(!userAlias.trim().isEmpty() || userAlias.trim().length() > 0)
							{
								group.addMember(userAlias);
								SVNUser svnUser = infoManager.getSvnUser(userAlias);
								if(null == svnUser)
								{
									svnUser = new SVNUser(userAlias, userAlias);
								}
								svnUser.addGroup(grpAlias);
								infoManager.updateUser(svnUser);
								System.out.println(svnUser);
							}
						}
					}
					System.out.println(group);
					infoManager.updateGroup(group);
				}
			}
			else if(TagParser.TAG_LOCATION == tagParser.getTagType())
			{	
				String locationPath = tagParser.getTagValue();
				SVNLocation location = infoManager.getLocation(locationPath);
				//Create new group if group does not exist.
				if(null == location )
				{
					location = new SVNLocation();
					location.setLocationName(locationPath);
					location.setLocationPath(locationPath);
					for(String ownerId: tagParser.getParsedTag().keySet())
					{
						Set<String> permissions = tagParser.getParsedTag().get(ownerId);
						for(String perm : permissions)
						{
							AccessUnit accessUnit = null;
							if(ownerId.toUpperCase().contains("@"))
							{
								ownerId = ownerId.replace("@","");
							}
							accessUnit = new AccessUnit(ownerId);
							accessUnit.setLocationPath(locationPath);
							accessUnit.setPermission(perm);
							location.addAccessUnit(accessUnit);
							System.err.println(accessUnit) ;
						}
					}

					System.out.println(location);
					infoManager.updateLocation(location);
				}

			}

		}
	}

	private Map<String, SVNTag> createTags()
	{
		List<Integer> lineNumbers = new ArrayList<Integer>(fileReader.getFileContent().keySet());
		Map<Integer,String> fileContents = fileReader.getFileContent();
		Map<String,SVNTag> tagsMap = new HashMap<String, SVNTag>();

		Collections.sort(lineNumbers);

		boolean tagStarted = false;
		SVNTag svnTag = null;;
		for(Integer key : lineNumbers)
		{
			String line = fileContents.get(key);
			line = line.trim();

			if(!line.startsWith("#") && line.startsWith("[") && line.endsWith("]"))
			{
				if(false == tagStarted)
				{
					if(null == svnTag)
					{
						svnTag = new SVNTag(line, key);
					}
					tagStarted = true;
				}
				else 
				{
					tagsMap.put(svnTag.getTagId(),svnTag);
					svnTag = new SVNTag(line, key); 
				}

			}
			else if(!line.startsWith("#"))
			{
				if(null != svnTag)
				{
					svnTag.addLine(line);
				}
			}
		}

		if(null != svnTag)
		{
			tagsMap.put(svnTag.getTagId(),svnTag);
		}
		return tagsMap;
	}//End
}
